package cqrtplm.log;

import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

/**
 * 通用对象比较工具类（统一使用RTComment注解）
 */
public class ObjectComparatorWithComment {

    /**
     * 比较两个对象的差异，返回包含类注释、修改信息的完整结果
     */
    public static <T> CompareResult compare(T oldObj, T newObj, String modifier) {
        // 校验对象合法性
        validateObjects(oldObj, newObj);
        Class<?> clazz = oldObj.getClass();

        // 构建比较结果
        CompareResult result = new CompareResult();
        result.setClassName(clazz.getSimpleName());
        result.setModifier(modifier);
        result.setModifyTime(new Timestamp(System.currentTimeMillis()));
        result.setDetails(compareFields(oldObj, newObj, clazz));

        return result;
    }

    /**
     * 比较对象的所有字段差异
     */
    private static <T> List<Difference> compareFields(T oldObj, T newObj, Class<?> clazz) {
        List<Difference> details = new ArrayList<>();
        List<Field> allFields = getAllFields(clazz);

        for (Field field : allFields) {
            try {
                field.setAccessible(true);
                Object oldValue = field.get(oldObj);
                Object newValue = field.get(newObj);

                if (!isValueEqual(oldValue, newValue)) {
                    Difference diff = new Difference();
                    diff.setF(field.getName()); // 字段名
                    diff.setO(oldValue != null ? oldValue.toString() : ""); // 旧值
                    diff.setN(newValue != null ? newValue.toString() : ""); // 新值
                    details.add(diff);
                }
            } catch (IllegalAccessException e) {
                throw new RuntimeException("比较字段失败：" + field.getName(), e);
            }
        }
        return details;
    }

    // 以下为工具方法（省略部分重复代码，保持核心逻辑）
    private static <T> void validateObjects(T oldObj, T newObj) {
        if (oldObj == null || newObj == null) {
            throw new IllegalArgumentException("比较对象不能为null");
        }
        if (!oldObj.getClass().equals(newObj.getClass())) {
            throw new IllegalArgumentException("对象类型不一致，无法比较");
        }
    }

    private static List<Field> getAllFields(Class<?> clazz) {
        List<Field> fields = new ArrayList<>();
        while (clazz != null && clazz != Object.class) {
            for (Field field : clazz.getDeclaredFields()) {
                fields.add(field);
            }
            clazz = clazz.getSuperclass();
        }
        return fields;
    }


    private static boolean isValueEqual(Object oldValue, Object newValue) {
        if (oldValue == null && newValue == null) return true;
        if (oldValue == null || newValue == null) return false;
        return oldValue.equals(newValue);
    }

    /**
     * 比较结果主类（包含类信息、修改信息和差异详情）
     */
    public static class CompareResult {
        private String className; // 类名
        private String modifier; // 修改人
        private Timestamp modifyTime; // 修改时间
        private List<Difference> details; // 差异详情数组

        // getter和setter
        public String getClassName() { return className; }
        public void setClassName(String className) { this.className = className; }
        public String getModifier() { return modifier; }
        public void setModifier(String modifier) { this.modifier = modifier; }
        public Timestamp getModifyTime() { return modifyTime; }
        public void setModifyTime(Timestamp modifyTime) { this.modifyTime = modifyTime; }
        public List<Difference> getDetails() { return details; }
        public void setDetails(List<Difference> details) { this.details = details; }
    }

    /**
     * 差异详情类（单个字段的差异）
     */
    public static class Difference {
        private String F; // 字段名
        private String O; // 旧值
        private String N; // 新值

        // getter和setter
        public String getF() { return F; }
        public void setF(String f) { F = f; }
        public String getO() { return O; }
        public void setO(String o) { O = o; }
        public String getN() { return N; }
        public void setN(String n) { N = n; }
    }
}
